Portfolios and CAPM: Borrowing and Saving Rates


Kerry Back

BUSI 721, Fall 2022
JGSB, Rice University

Portfolio return

\[r_{p}=r_{f}+\sum_{i=1}^n w_{i}(r_{i}-r_{f})\]

Portfolio expected return

\[\bar{r}_{p}=r_{f}+\sum_{i=1}^n w_{i}(\bar{r}_{i}-r_{f})=r_{f}+(\bar{r}-r_{f}1_{n})^⊤w\]

Portfolio variance

\[var(r_{p})=w^⊤Cw\]

where \(C\) = covariance matrix, \(1_n\)=vector of 1’s.

Efficient and Optimal Portfolios

The minimum risk portfolio achieving a target expected return minimizes

\(w^⊤Cw\) subject to \(r_{f}+(\bar{r}-r_{f}1_n)^⊤w=\text{target}\)

The optimal portfolio for an investor with risk aversion \(\text{A}\) maximizes

\[r_f + (\bar{r}-r_f1_n)^⊤w-\frac{1}{2}\text{A}w^⊤\text{C}w\]

These are quadratic programming problems.

Optimal Portfolios

Conventional to write it as minimization:

minimize \[\frac{\text{A}}{2}w^⊤\text{C}w-r_{f}-(\bar{r}-r_{f}1_n)^⊤w\]

Solution from last module

import numpy as np
# standard deviations
sds = np.array([0.15, 0.25, 0.35])
S = np.diag(sds)
# correlations
r12 = 0.15
r13 = 0.6
r23 = 0.3
R = np.identity(3)
R[0, 1] = R[1, 0] = r12
R[0, 2] = R[2, 0] = r13
R[1, 2] = R[2, 1] = r23
# covariance matrix
C = S @ R @ S
# optimal portfolio
r = 0.04
means = np.array([0.06, 0.1, 0.09])
raver = 4
w = np.linalg.solve(C, (means-r)/raver)

Solution is \(\text{w}_1=0.14\) \(\text{w}_2=0.22\) \(\text{w}_3=0.02\)  

save 0.62

Different Borrowing and Saving Rates

\(r_{b}=\) borrowing rate > saving rate \(= r_{s}\)  

\(x_{b} \geq 0 =\) amount borrowed
\(x_{s} \geq 0 =\) amount saved

Portfolio expected return: \[\small x_{s}r_{s}-x_{b}r_{b}+\bar{r}^⊤w\]

Assets=Investments:

\[\tiny x_{s}+\sum_{i=1}^n w_{i} = 1 + x_{b} \iff x_{s}+1_{n}^⊤w=1+x_{b}\]

Optimal Portfolios

minimize \(\frac{\text{A}}{2}w^⊤\text{C}w-x_{s}r_{s}+x_{b}r_{b}-\bar{r}^⊤w\)  

subject to \(-x_{s} \leq 0, -x_{b} \leq 0, x_{s}-x{b}+1_n^⊤w=1\)

  • choice vector: \((x_s,x_b,w)^⊤\)
  • \((\text{n}+2)\times({\text{n}+2})\) quadratic term with zeros and \(\text{AC}\) in bottom right
  • linear term: \((-1,1,-\bar{r})^⊤\)
  • \(2 \times \text{(n+2)}\) inequality matrix with rows
    \((-1,0,\cdots,0),(0,-1,0,\cdots,0)\)
  • \(1 \times \text{(n+2)}\) equality matrix: \((1,-1,1_n)\)
  • right-hand side of inequality = 0’s, right-hand side of equality=1

rs = 0.04
rb = 0.08
# quadratic and linear terms
Q = np.zeros((5, 5))
Q[2:, 2:] = raver*C
p = np.concatenate(([-rs, rb], -means))
# inequalities
G = np.zeros((2, 5))
G[0, 0] = G[1, 1] = -1
h = np.zeros(2)
# equalities
A = np.concatenate(([1, -1], np.ones(3)))
b = np.ones(1)

cvxopt

from cvxopt import matrix
from cvxopt.solvers import qp
Q = matrix(Q, (5, 5))
p = matrix(p, (5, 1))
G = matrix(G, (2, 5))
h = matrix(h, (2, 1))
A = matrix(A, (1, 5))
b = matrix(b, (1, 1))
sol = qp(Q, p, G, h, A, b)
xs, xb, w1, w2, w3 = np.array(sol["x"])

Solution is same as in last module for these parameters. Higher borrowing rate doesn’t matter for someone who doesn’t want to borrow at a lower rate.

3K

HTML tutorial